package selectors;

import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.Map.Entry;

import strategies.Strategy;

import base.Environment;

import agents.Agent;
import agents.AverageUtility;

public class PreferentialStrategySelector extends StrategySelector {

	private class FittestStrategyComparator implements Comparator<Strategy> {
		private Agent agent;
		
		public FittestStrategyComparator(Agent agent) {
			this.agent = agent;
		}
		
		@Override
		public int compare(Strategy s1, Strategy s2) {
			AverageUtility u1 = agent.getStrategies().get(s1);
			AverageUtility u2 = agent.getStrategies().get(s2);
			
			if (u1.getAverageUtility() > u2.getAverageUtility())
				return -1;
			else if (u1.getAverageUtility() < u2.getAverageUtility())
				return 1;
			
			return u1.getSteps() - u2.getSteps();
		}
	}
	
	
	public PreferentialStrategySelector(Environment env) {}
	
	
	@Override
	public Strategy selectStrategy(Agent agent) {
		
		Strategy strategy = null;
		double max = Double.NEGATIVE_INFINITY;
		
		for (Entry<Strategy, AverageUtility> entry : agent.getStrategies().entrySet())
			if (entry.getValue().getAverageUtility() > max) {
				strategy = entry.getKey();
				max = entry.getValue().getAverageUtility();
			}
		
		// weak!
		if (max < 0d)
			return strategy;
		
		LinkedList<Strategy> list = new LinkedList<Strategy>();
		list.addAll(agent.getStrategies().keySet());
		Collections.sort(list, new FittestStrategyComparator(agent));
		double r = Math.random();
		return list.get((int) (r * r * list.size()));
	}
}
